package com.pkk.penguin.frame.know.java.Javacoreknowledge.thread.threadpool;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.DiscardPolicy;
import java.util.concurrent.TimeUnit;
import org.junit.Test;

/**
 * @description: 线程池简单的创建
 * @author: peikunkun
 * @create: 2019-12-25 13:21
 **/
public class ThreadPoolSimple {

  @Test
  public void Administrator_11_20191225132133() {
    System.out.println("欢迎使用单元测试方法【Administrator_11()_20191225132133】");
    System.out.println("此方法测试描述：【Executors的自由创建】");

    ExecutorService executorService = Executors.newFixedThreadPool(10);
    //执行19次这个方法,其中有10个线程供它选择执行
    for (int i = 0; i < 19; i++) {
      executorService.execute(new Runnable() {
        @Override
        public void run() {
          System.out.println(Thread.currentThread());
        }
      });
    }
  }


  @Test
  public void Administrator_34_20200110155342() throws InterruptedException {
    System.out.println("欢迎使用单元测试方法【Administrator_34()_20200110155342】");
    System.out.println("此方法测试描述：【】");

    /*线程池中的线程已经用完了，无法继续为新任务服务，同时，等待队列也已经排满了，再也
    塞不下新任务了。这时候我们就需要拒绝策略机制合理的处理这个问题。
    JDK 内置的拒绝策略如下：
    1. AbortPolicy ： 直接抛出异常，阻止系统正常运行。
    2. CallerRunsPolicy ： 只要线程池未关闭，该策略直接在调用者线程中，运行当前被丢弃的
    任务。显然这样做不会真的丢弃任务，但是，任务提交线程的性能极有可能会急剧下降。
    3. DiscardOldestPolicy ： 丢弃最老的一个请求，也就是即将被执行的一个任务，并尝试再
    次提交当前任务。
    4. DiscardPolicy ： 该策略默默地丢弃无法处理的任务，不予任何处理。如果允许任务丢
    失，这是最好的一种方案。
    以上内置拒绝策略均实现了 RejectedExecutionHandler 接口，若以上策略仍无法满足实际
    需要，完全可以自己扩展 RejectedExecutionHandler 接口*/

    /**
     * Java 中的阻塞队列
     * 1.  ArrayBlockingQueue ：由数组结构组成的有界阻塞队列。
     * 2.  LinkedBlockingQueue ：由链表结构组成的有界阻塞队列。
     * 3.  PriorityBlockingQueue ：支持优先级排序的无界阻塞队列。
     * 4.  DelayQueue：使用优先级队列实现的无界阻塞队列。
     * 5.  SynchronousQueue：不存储元素的阻塞队列。
     * 6.  LinkedTransferQueue：由链表结构组成的无界阻塞队列。
     * 7.  LinkedBlockingDeque：由链表结构组成的双向阻塞队列
     */

    //核心线程数-始终保留的线程数
    int corePoolSize = 10;
    //最大线程数
    int maximumPoolSize = 20;
    //空闲线程存活时间
    long keepAliveTime = 1L;
    //空闲线程存活时间单位
    TimeUnit unit = TimeUnit.SECONDS;
    //任务队列
    BlockingQueue<Runnable> workQueue = new LinkedTransferQueue();
    //线程工厂，用于创建线程，一般用默认的即可
    ThreadFactory threadFactory = Executors.defaultThreadFactory();
    //拒绝策略，当任务太多来不及处理，如何拒绝任务
    RejectedExecutionHandler handler = new DiscardPolicy();

    //创建核心线程数
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit,
        workQueue, threadFactory, handler);

    //任务数
    int taskNum = 100;
    int[] tasks = new int[taskNum];
    for (int i = 0; i < taskNum; i++) {
      tasks[i] = i;
    }

    //程序计数器(等待这些个线程执行完在执行其他的)
    CountDownLatch countDownLatch = new CountDownLatch(taskNum);

    //线程的执行
    for (int i = 0; i < taskNum; i++) {
      int finalI = i;
      threadPoolExecutor.execute(new Runnable() {
        @Override
        public void run() {
          System.out.println(Thread.currentThread().getName() + "-" + finalI);
          countDownLatch.countDown();
        }
      });
    }

    System.out.println("***等待 " + taskNum + " 个子线程执行完毕...");
    countDownLatch.await();
    System.out.println("***" + taskNum + "个子线程已经执行完毕");
    System.out.println("***继续执行主线程");

    System.out.println("***活跃线程数:" + threadPoolExecutor.getActiveCount());
    System.out.println("***核心线程数:" + threadPoolExecutor.getCorePoolSize());
    System.out.println("***任务数量:" + threadPoolExecutor.getTaskCount());
    System.out.println("***是否关闭:" + threadPoolExecutor.isShutdown());
    //threadPoolExecutor.shutdown();
    System.out.println("***是否关闭:" + threadPoolExecutor.isShutdown());


  }


}
